package com.budwk.app.sqfw.services.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.budwk.app.common.config.AppException;
import com.budwk.app.sqfw.component.CommonComponent;
import com.budwk.app.sqfw.constants.CommonConstants;
import com.budwk.app.sqfw.dto.PersonnelTagDTO;
import com.budwk.app.sqfw.enums.SupportBusinessTypeEnum;
import com.budwk.app.sqfw.models.HouseInfo;
import com.budwk.app.sqfw.models.PersonInfo;
import com.budwk.app.sqfw.models.Sqfw_formSummary_new;
import com.budwk.app.sqfw.services.HouseInfoService;
import com.budwk.app.sqfw.services.PersonInfoService;
import com.budwk.app.sqfw.services.SqfwFormsummaryNewService;
import com.budwk.app.sqfwV2.component.HouseInfoComponent;
import com.budwk.app.sqfwV2.component.HouseholdComponent;
import com.budwk.app.sqfwV2.component.PersonInfoComponent;
import com.budwk.app.sqfwV2.dto.dto.PersonInfoDTO;
import com.budwk.app.sqfwV2.dto.vo.HouseRelatPerson;
import com.budwk.app.sqfwV2.dto.vo.PersonHouseVo;
import com.budwk.app.sqfwV2.dto.vo.PersonInfoReqVo;
import com.budwk.app.sys.models.Sys_user;
import com.budwk.app.sys.services.SysUserService;
import com.budwk.app.util.poiUtils.nutzBeanUtils.NutzIocUtils;
import com.budwk.starter.common.page.Pagination;
import com.budwk.starter.common.result.Result;
import com.budwk.starter.database.service.BaseServiceImpl;
import com.budwk.starter.security.utils.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.impl.FileSqlManager;
import org.nutz.dao.impl.NutDao;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@IocBean(args = {"refer:dao"})
@Slf4j
public class PersonInfoServiceImpl extends BaseServiceImpl<PersonInfo> implements PersonInfoService {
    public PersonInfoServiceImpl(Dao dao) {
        super(dao);
        // 加载配置文件
        ((NutDao)dao).setSqlManager(new FileSqlManager("db/personInfo/personInfo.sql"));
    }

    @Inject
    private SysUserService userService;
    @Inject
    private SqfwFormsummaryNewService formsummaryNewService;
    @Inject("taskQueryExecutor")
    private ThreadPoolExecutor taskQueryExecutor;

    @Override
    public Result<Pagination> listPersonByPage(PersonInfoReqVo reqVo) {
        Cnd cnd = Cnd.NEW();
        SqlExpressionGroup where = cnd.where();
        HouseholdComponent.handleUserQueryAuth(where);
        // 关键字 模糊查询姓名、身份证、手机号、住址。
        if (StringUtils.isNotEmpty(reqVo.getQueryCondition())) {
            SqlExpressionGroup a1 = Cnd.exps(PersonInfo::getName, "like", "%" + reqVo.getQueryCondition() + "%");
            SqlExpressionGroup a2 = Cnd.exps(PersonInfo::getIdNumber, "like", "%" + reqVo.getQueryCondition() + "%");
            SqlExpressionGroup a3 = Cnd.exps(PersonInfo::getPhone, "like", "%" + reqVo.getQueryCondition() + "%");
            SqlExpressionGroup a4 = Cnd.exps(PersonInfo::getAddress, "like", "%" + reqVo.getQueryCondition() + "%");
            where.and(a1.or(a2).or(a3).or(a4));
        }
        if (StringUtils.isNotEmpty(reqVo.getBusinessType())) {
            where.andLike(PersonInfo::getBusinessType, reqVo.getBusinessType());
        }
        // 只查询入户数据
        where.andEquals(PersonInfo::isDeleted, false); // 未删除的数据
        // 人员类型
        if (StringUtils.isNotEmpty(reqVo.getSpecialMarkStr())) {
            cnd.and("special_mark", "@>", "[{\"tag\":[{\"key\":\""+ reqVo.getSpecialMarkStr() +"\"}]}]");
        }
        cnd.getOrderBy().desc(PersonInfo::getUpdateDate);
        Pagination pagination = this.listPage(reqVo.getPageNo(), reqVo.getPageSize(), cnd);
        int totalCount = pagination.getTotalCount();
        if (totalCount == 0) {
            return Result.data(pagination);
        }
        // 导入的数据一般没有详细地址 需要初始化更新
        List<PersonInfo> list = pagination.getList(PersonInfo.class);
        CompletableFuture[] cf = list.stream().map(personInfo -> CompletableFuture.runAsync(() ->
                PersonInfoComponent.handlePersonData(personInfo), taskQueryExecutor)
                .thenApply(r -> r)).toArray(CompletableFuture[]::new);
        CompletableFuture.allOf(cf).join();
        return Result.data(pagination);
    }

    @Override
    public void deleteData(PersonInfoReqVo reqVo) {
        if (StringUtils.isEmpty(reqVo.getDeleteReason())) {
            throw new AppException("删除原因不能为空！");
        }
        if (StringUtils.isEmpty(reqVo.getId())) {
            throw new AppException("删除数据id不能为空！");
        }
        PersonInfo personInfo = this.fetch(reqVo.getId());
        personInfo.setLatestStatus(reqVo.getDeleteReason())
                .setDeleted(true)
                .setDeleteReason(reqVo.getDeleteReason())
                .setUpdateBy(SecurityUtil.getUserId())
                .setUpdateDate(LocalDateTime.now());
        this.updateIgnoreNull(personInfo);
    }

    @Override
    @Aop(TransAop.READ_COMMITTED)
    public PersonInfo submitData(PersonInfoDTO reqVo) {
        // 1 参数校验
        PersonInfoComponent.checkPersonData(reqVo);
        // 2 业务逻辑实现
        if (StringUtils.isEmpty(reqVo.getId())) {
            return savePerson(reqVo);
        }
        return updatePerson(reqVo);
    }

    private PersonInfo savePerson(PersonInfoDTO reqVo) {
        reqVo.setCreateBy(SecurityUtil.getUserId()).setCreateDate(LocalDateTime.now())
                .setUpdateBy(SecurityUtil.getUserId()).setUpdateDate(LocalDateTime.now())
                .setDeleted(false)
                .setBusinessType(SupportBusinessTypeEnum.PERSON_TYPE.getName())
                .setLatestStatus("正常")
                .setId(String.valueOf(IdUtil.getSnowflakeNextId()))
                .setSpecialMark(List.of(JSONObject.toJavaObject(reqVo.getSpecialMarkTag(), PersonnelTagDTO.class)));
        this.insert(reqVo);
        // 记录走访记录
        addRecord(reqVo, reqVo.getDetailAddress());
        // 获取关联的房屋信息
        List<PersonHouseVo> houses = reqVo.getHouses();
        if (CollectionUtil.isEmpty(houses)) {
            return reqVo;
        }
        // 更新房屋关联人信息
        HouseInfoService houseInfoService = NutzIocUtils.getBean(HouseInfoService.class);
        houseInfoService.updatePersonHouse(reqVo);
        return reqVo;
    }

    private void addRecord(PersonInfoDTO reqVo, String detailAddress) {
        List<PersonHouseVo> houses = reqVo.getHouses();
        PersonInfoDTO reqVo1 = new PersonInfoDTO();
        BeanUtil.copyProperties(reqVo, reqVo1);

        if (CollectionUtil.isNotEmpty(houses)) {
            List<PersonHouseVo> collect = houses.stream().filter(e -> StringUtils.isEmpty(e.getDeleted()) || e.getDeleted().equals(CommonConstants.NO_CHINA)).collect(Collectors.toList());
            reqVo1.setHouses(collect);
        }
        reqVo1.setPersonId(reqVo1.getId());
        HouseholdComponent.insertRecord(JSONObject.toJSONString(reqVo1), SupportBusinessTypeEnum.PERSON_TYPE.getName(), detailAddress);
    }

    private void addSubmitRecord(PersonInfoDTO reqVo, PersonInfo personInfo) {
        if (StringUtils.isEmpty(reqVo.getSubmitType())) {
            return;
        }
        // 如果是走访的话 需要记录
        if ("2".equals(reqVo.getSubmitType())) {
            addRecord(reqVo, personInfo.getDetailAddress());
            return;
        }
        // 编辑 需要判断走访记录是否被删除 如果被删除 需要重新记录
        List<Sqfw_formSummary_new> list = listPersonDetail(personInfo.getId());
        if (CollectionUtil.isEmpty(list)) {
            addRecord(reqVo, personInfo.getDetailAddress());
        }
    }


    private PersonInfo updatePerson(PersonInfoDTO reqVo) {
        PersonInfo personInfo = this.fetch(reqVo.getId());
        // 修改用户信息
        reqVo.setUpdateBy(SecurityUtil.getUserId()).setUpdateDate(LocalDateTime.now());
        // 解析标签
        List<PersonnelTagDTO> specialMark = HouseInfoComponent.handleSpecialMark(personInfo, reqVo.getSpecialMarkTag());
        if (specialMark != null) {
            reqVo.setSpecialMark(specialMark);
            reqVo.setBusinessType(specialMark.stream().map(PersonnelTagDTO::getBusinessType).collect(Collectors.joining(",")));
        }
        this.updateIgnoreNull(reqVo);
        // 记录走访记录
        addSubmitRecord(reqVo, personInfo);
        // 获取关联的房屋信息
        List<PersonHouseVo> houses = reqVo.getHouses();
        if (CollectionUtil.isEmpty(houses)) {
            return reqVo;
        }
        // 更新房屋关联人信息
        HouseInfoService houseInfoService = NutzIocUtils.getBean(HouseInfoService.class);
        houseInfoService.updatePersonHouse(reqVo);
        return reqVo;
    }

    @Override
    public List<PersonHouseVo> queryRelateHouse(String personId) {
        List<PersonHouseVo> list = new ArrayList<>();
        Cnd cnd = Cnd.NEW();
        cnd.and("house_relat_peoples::jsonb", "@>", "[{\"personId\": \""+ personId +"\"}]");
        HouseInfoService houseInfoService = NutzIocUtils.getBean(HouseInfoService.class);
        List<HouseInfo> houseInfos = houseInfoService.query(cnd);
        if (CollectionUtil.isEmpty(houseInfos)) {
            return list;
        }
        for (HouseInfo houseInfo : houseInfos) {
            Optional<HouseRelatPerson> optional = houseInfo.getHouseRelatPeoples().stream().filter(e -> e.getPersonId().equals(personId)).findFirst();
            PersonHouseVo personHouseVo = new PersonHouseVo();
            HouseRelatPerson hrp = optional.get();
            personHouseVo.setId(houseInfo.getId())
                    .setPersonType(hrp.getPersonType())
                    .setRoomNumber(houseInfo.getRoomNumber())
                    .setAddress(houseInfo.getDetailAddress())
                    .setDeleted(CommonConstants.NO_CHINA);
            list.add(personHouseVo);
        }
        return list;
    }

    @Override
    public PersonInfo getPersonInfo(String idcard) {
        if (StringUtils.isEmpty(idcard)) {
            return null;
        }
        // 按照五级+身份证号检查用户是否存在
        Sys_user user = CommonComponent.getCurrentUser();
        Cnd cnd = Cnd.NEW();
        SqlExpressionGroup where = cnd.where();
        where.andEquals(PersonInfo::getProvince, user.getProvince())
                .andEquals(PersonInfo::getCity, user.getCity())
                .andEquals(PersonInfo::getDistrict, user.getDistrict())
                .andEquals(PersonInfo::getCounty, user.getCounty())
                .andEquals(PersonInfo::getCommunity, user.getCommunity())
                .andEquals(PersonInfo::getIdNumber, idcard)
                .andEquals(PersonInfo::isDeleted, false);
        PersonInfo personInfo = this.fetch(cnd);
        log.info("person getPerson res: {}", JSONObject.toJSONString(personInfo));
        return personInfo;
    }

    @Override
    public Result<Pagination> listPersonRecordByPage(PersonInfoReqVo reqVo) {
        if (StringUtils.isEmpty(reqVo.getId())) {
            return Result.success();
        }
        Cnd cnd = Cnd.NEW();
        SqlExpressionGroup criSql = cnd.where();
        if (StringUtils.isNotEmpty(reqVo.getId())) {
            criSql.andEquals("param_data->>'personId'", reqVo.getId());
        }
        criSql.andEquals(Sqfw_formSummary_new::getType, SupportBusinessTypeEnum.PERSON_TYPE.getName());
        cnd.getOrderBy().desc(Sqfw_formSummary_new::getFillDate);
        Pagination pagination = formsummaryNewService.listPage(reqVo.getPageNo(), reqVo.getPageSize(), cnd);
        return Result.data(pagination);
    }

    @Override
    public Sqfw_formSummary_new getPersonDetail(String personId, String type) {
        PersonInfo personInfo = this.fetch(personId);
        if (personInfo == null) {
            throw new AppException("人员不存在！");
        }
        Cnd cnd = Cnd.NEW();
        SqlExpressionGroup criSql = cnd.where();
        criSql.andEquals("param_data->>'personId'", personId)
                .andEquals(Sqfw_formSummary_new::getType, StringUtils.isEmpty(type) ? personInfo.getBusinessType() : type);
        // 获取最新的一条数据
        cnd.limit(1);
        cnd.getOrderBy().desc(Sqfw_formSummary_new::getFillDate);
        Sqfw_formSummary_new summaryNew = formsummaryNewService.fetch(cnd);
        if (summaryNew != null) {
            return summaryNew;
        }
        // 查询人员的基本信息
        summaryNew = new Sqfw_formSummary_new();
        CommonComponent.buildBaseSqfwFormSummaryNew(summaryNew);
        summaryNew.setParamData(JSONObject.toJSONString(personInfo));
        return summaryNew;
    }

    @Override
    public List<Sqfw_formSummary_new> listPersonDetail(String personId) {
        Cnd cnd = Cnd.NEW();
        SqlExpressionGroup criSql = cnd.where();
        criSql.andEquals("param_data->>'personId'", personId)
                .andEquals(Sqfw_formSummary_new::getType, SupportBusinessTypeEnum.PERSON_TYPE.getName());
        // 获取最新的一条数据
        cnd.getOrderBy().desc(Sqfw_formSummary_new::getFillDate);
        return formsummaryNewService.query(cnd);
    }

    @Override
    public PersonInfo saveOrUpdatePerson(PersonInfoDTO reqVo) {
        // 1 参数校验
        PersonInfoComponent.checkPersonData(reqVo);
        // 2 构建基本信息
        PersonInfoComponent.buildPersonInfo(reqVo);
        // 3 提交或者修改
        if (StringUtils.isEmpty(reqVo.getId())) {
            this.insert(reqVo);
            return reqVo;
        }
        this.updateIgnoreNull(reqVo);
        return reqVo;
    }

    @Override
    public PersonInfo queryPersonDetail(String personId) {
        PersonInfo personInfo = this.fetch(personId);
        if (personInfo == null) {
            throw new AppException("人员不存在！");
        }
        return personInfo;
    }
}
